<!DOCTYPE html>
<html>
  <head>
    <title>WebRTC Video Chat</title>
    <script src="https://cdn.socket.io/4.0.0/socket.io.min.js"></script>
    <style>
      body {
        font-family: Arial, sans-serif;
        margin: 0;
        padding: 20px;
        background-color: #f0f0f0;
        display: flex;
        flex-direction: column;
        height: 100vh;
      }
      h1 {
        text-align: center;
        color: #333;
        margin-bottom: 10px;
      }
      #roomSelection {
        text-align: center;
        margin-bottom: 20px;
      }
      #roomInput {
        padding: 8px;
        font-size: 16px;
        width: 200px;
        border: 1px solid #ccc;
        border-radius: 4px;
      }
      button {
        padding: 8px 16px;
        font-size: 16px;
        margin: 0 5px;
        background-color: #007bff;
        color: white;
        border: none;
        border-radius: 4px;
        cursor: pointer;
      }
      button:hover {
        background-color: #0056b3;
      }
      #mainContainer {
        display: flex;
        flex: 1;
        gap: 20px;
      }
      #videoLayout {
        flex: 3;
        display: flex;
        flex-direction: column;
        gap: 20px;
      }
      #localVideoContainer {
        text-align: center;
        position: relative;
      }
      #localVideo {
        width: 400px;
        height: 300px;
        object-fit: cover;
        border-radius: 8px;
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        background-color: aqua;
        position: relative;
      }
      #localVideo::after {
        content: 'Local (ID: local)';
        position: absolute;
        top: 10px;
        left: 10px;
        color: white;
        background-color: rgba(0, 0, 0, 0.6);
        padding: 5px 10px;
        border-radius: 4px;
      }
      #remoteVideoContainer {
        display: flex;
        justify-content: center;
        gap: 10px;
        flex-wrap: wrap;
      }
      .remoteVideo {
        width: 150px;
        height: 150px;
        object-fit: cover;
        border-radius: 8px;
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        background-color: gray;
        position: relative;
      }
      .remoteVideo::after {
        content: attr(data-id);
        position: absolute;
        top: 10px;
        left: 10px;
        color: white;
        background-color: rgba(0, 0, 0, 0.6);
        padding: 5px 10px;
        border-radius: 4px;
      }
      #chatSection {
        flex: 1;
        display: flex;
        flex-direction: column;
        gap: 10px;
        max-width: 300px;
      }
      #chatInput {
        width: 100%;
        padding: 8px;
        font-size: 16px;
        border: 1px solid #ccc;
        border-radius: 4px;
        resize: none;
      }
      #sendChat {
        align-self: flex-end;
        width: 100px;
      }
      #chatDisplay {
        flex: 1;
        background-color: white;
        border: 1px solid #ccc;
        border-radius: 4px;
        padding: 10px;
        overflow-y: auto;
        font-size: 14px;
      }
      .chatMessage {
        margin: 5px 0;
        padding: 5px;
        background-color: #e9ecef;
        border-radius: 4px;
      }
      #controls {
        text-align: center;
        margin-top: 20px;
      }
      .muteButton, .videoButton {
        background-color: #28a745;
      }
      .muteButton.muted, .videoButton.off {
        background-color: #dc3545;
      }
    </style>
  </head>
  <body>
    <h1>WebRTC Video Chat</h1>
    <div id="roomSelection">
      <input type="text" id="roomInput" placeholder="Enter room name" />
      <button id="joinButton">Join Room</button>
    </div>
    <div id="mainContainer">
      <div id="videoLayout">
        <div id="localVideoContainer">
          <video id="localVideo" autoplay muted playsinline></video>
        </div>
        <div id="remoteVideoContainer"></div>
      </div>
      <div id="chatSection">
        <textarea id="chatInput" placeholder="Type your message here..." rows="3"></textarea>
        <button id="sendChat">Send</button>
        <div id="chatDisplay"></div>
      </div>
    </div>
    <div id="controls">
      <button id="muteMicButton" class="muteButton">Mute Mic</button>
      <button id="muteVideoButton" class="videoButton">Mute Video</button>
      <button id="muteAllMicButton" style="display: none;">Mute All Mics</button>
      <button id="muteAllVideoButton" style="display: none;">Mute All Videos</button>
      <button id="startButton" style="display: none;">Start Call</button>
      <button id="endButton">End Call</button>
    </div>

    <script>
      let localStream;
      let peerConnections = {};
      let chatHistory = [];
      let isRoomOwner = false;
      let currentRoom = null;
      const socket = io('http://127.0.0.1:4000');
      const servers = {
        iceServers: [{ urls: 'stun:stun.l.google.com:19302' }],
      };

      const joinButton = document.getElementById('joinButton');
      const roomInput = document.getElementById('roomInput');
      const startButton = document.getElementById('startButton');
      const chatInput = document.getElementById('chatInput');
      const sendChat = document.getElementById('sendChat');
      const chatDisplay = document.getElementById('chatDisplay');
      const muteMicButton = document.getElementById('muteMicButton');
      const muteVideoButton = document.getElementById('muteVideoButton');
      const muteAllMicButton = document.getElementById('muteAllMicButton');
      const muteAllVideoButton = document.getElementById('muteAllVideoButton');

      async function joinRoom() {
        const roomName = roomInput.value.trim();
        if (!roomName) {
          alert('Please enter a room name');
          return;
        }

        try {
          localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
          document.getElementById('localVideo').srcObject = localStream;
          socket.emit('joinRoom', roomName);
          currentRoom = roomName;

          document.getElementById('roomSelection').style.display = 'none';
          startButton.style.display = 'inline';
        } catch (error) {
          if (error.name === 'NotReadableError' || error.name === 'TrackStartError') {
            alert('Camera or microphone is in use by another application. Please close it and try again.');
          } else {
            console.error('Error accessing media devices:', error);
            alert('Failed to access camera/microphone: ' + error.message);
          }
        }
      }

      socket.on('setRoomOwner', (isOwner) => {
        console.log('Am I room owner?', isOwner);
        isRoomOwner = isOwner;
        muteAllMicButton.style.display = isOwner ? 'inline' : 'none';
        muteAllVideoButton.style.display = isOwner ? 'inline' : 'none';
      });

      socket.on('offer', async (id, description) => {
        console.log('Received offer from:', id);
        if (!peerConnections[id]) {
          createPeerConnection(id);
        }
        await peerConnections[id].setRemoteDescription(description);
        const answer = await peerConnections[id].createAnswer();
        await peerConnections[id].setLocalDescription(answer);
        socket.emit('answer', id, peerConnections[id].localDescription);
      });

      socket.on('answer', async (id, description) => {
        console.log('Received answer from:', id);
        if (peerConnections[id]) {
          await peerConnections[id].setRemoteDescription(description);
        }
      });

      socket.on('candidate', (id, candidate) => {
        console.log('Received candidate from:', id);
        if (peerConnections[id]) {
          peerConnections[id].addIceCandidate(new RTCIceCandidate(candidate));
        }
      });

      socket.on('userJoined', async (userId) => {
        console.log('User joined:', userId);
        if (!peerConnections[userId]) {
          createPeerConnection(userId);
          const offer = await peerConnections[userId].createOffer();
          await peerConnections[userId].setLocalDescription(offer);
          socket.emit('offer', userId, peerConnections[userId].localDescription);
        }
        chatHistory.forEach(item => {
          socket.emit('chat', item.userId, item.message);
        });
      });

      socket.on('chat', (userId, message) => {
        console.log('Received chat:', { userId, message });
        if (!chatHistory.some(item => item.userId === userId && item.message === message)) {
          chatHistory.push({ userId, message, timestamp: new Date().toISOString() });
          updateChatDisplay();
        }
      });

      socket.on('muteAllMic', () => {
        console.log('Received mute all mic command');
        localStream.getAudioTracks().forEach(track => {
          track.enabled = false;
        });
        muteMicButton.classList.add('muted');
        muteMicButton.textContent = 'Unmute Mic';
      });

      socket.on('muteAllVideo', () => {
        console.log('Received mute all video command');
        localStream.getVideoTracks().forEach(track => {
          track.enabled = false;
        });
        muteVideoButton.classList.add('off');
        muteVideoButton.textContent = 'Unmute Video';
      });

      function createPeerConnection(id) {
        peerConnections[id] = new RTCPeerConnection(servers);

        localStream.getTracks().forEach(track => peerConnections[id].addTrack(track, localStream));

        peerConnections[id].onicecandidate = event => {
          if (event.candidate) {
            socket.emit('candidate', id, event.candidate);
          }
        };

        peerConnections[id].ontrack = event => {
          const remoteVideoContainer = document.getElementById('remoteVideoContainer');
          let remoteVideo = document.getElementById(`remote-${id}`);
          if (!remoteVideo) {
            remoteVideo = document.createElement('video');
            remoteVideo.id = `remote-${id}`;
            remoteVideo.className = 'remoteVideo';
            remoteVideo.setAttribute('data-id', `Remote (ID: ${id})`);
            remoteVideo.autoplay = true;
            remoteVideo.playsInline = true;
            remoteVideoContainer.appendChild(remoteVideo);
          }
          remoteVideo.srcObject = event.streams[0];
        };

        peerConnections[id].onconnectionstatechange = () => {
          if (peerConnections[id].connectionState === 'disconnected') {
            const remoteVideo = document.getElementById(`remote-${id}`);
            if (remoteVideo) remoteVideo.remove();
            delete peerConnections[id];
          }
        };
      }

      function updateChatDisplay() {
        chatDisplay.innerHTML = chatHistory
          .map(item => `<div class="chatMessage">[${item.userId}]: ${item.message}</div>`)
          .join('');
        chatDisplay.scrollTop = chatDisplay.scrollHeight;
      }

      joinButton.onclick = joinRoom;
      startButton.onclick = () => {
        console.log('Call started');
      };

      sendChat.onclick = () => {
        const message = chatInput.value.trim();
        if (message) {
          socket.emit('chat', socket.id, message);
          chatInput.value = '';
        }
      };

      muteMicButton.onclick = () => {
        const audioTracks = localStream.getAudioTracks();
        const isMuted = audioTracks[0].enabled;
        audioTracks.forEach(track => {
          track.enabled = !isMuted;
        });
        muteMicButton.classList.toggle('muted');
        muteMicButton.textContent = isMuted ? 'Unmute Mic' : 'Mute Mic';
      };

      muteVideoButton.onclick = () => {
        const videoTracks = localStream.getVideoTracks();
        const isOff = videoTracks[0].enabled;
        videoTracks.forEach(track => {
          track.enabled = !isOff;
        });
        muteVideoButton.classList.toggle('off');
        muteVideoButton.textContent = isOff ? 'Unmute Video' : 'Mute Video';
      };

      muteAllMicButton.onclick = () => {
        if (isRoomOwner) {
          socket.emit('muteAllMic', currentRoom);
          localStream.getAudioTracks().forEach(track => {
            track.enabled = false;
          });
          muteMicButton.classList.add('muted');
          muteMicButton.textContent = 'Unmute Mic';
        }
      };

      muteAllVideoButton.onclick = () => {
        if (isRoomOwner) {
          socket.emit('muteAllVideo', currentRoom);
          localStream.getVideoTracks().forEach(track => {
            track.enabled = false;
          });
          muteVideoButton.classList.add('off');
          muteVideoButton.textContent = 'Unmute Video';
        }
      };

      document.getElementById('endButton').onclick = () => {
        Object.keys(peerConnections).forEach(id => {
          peerConnections[id].close();
          delete peerConnections[id];
          const remoteVideo = document.getElementById(`remote-${id}`);
          if (remoteVideo) remoteVideo.remove();
        });
        if (localStream) {
          localStream.getTracks().forEach(track => track.stop());
          document.getElementById('localVideo').srcObject = null;
        }
        socket.disconnect();
        document.getElementById('roomSelection').style.display = 'block';
        startButton.style.display = 'none';
        chatDisplay.innerHTML = '';
        chatHistory = [];
        isRoomOwner = false;
        muteAllMicButton.style.display = 'none';
        muteAllVideoButton.style.display = 'none';
      };
    </script>
  </body>
</html>